﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using Newtonsoft.Json;
using ZilLion.Core.Log;
using ZilLion.Core.TaskManager.Client.Command;
using ZilLion.TaskManager.Entity;
using ZilLion.TaskManager.Entity.Entity;
using ZilLion.TaskManager.Repository;


namespace ZilLion.Core.TaskManager.Client
{
    /// <summary>
    ///     命令监听
    /// </summary>
    public class CommandQueueProcessor
    {
        private static readonly object _lockRunLoop = new object();
        private static readonly TaskStateRespository TaskStateRespository = new TaskStateRespository();
        private static readonly TaskCommandRespository TaskCommandRespository = new TaskCommandRespository();
        private static readonly Thread thread;

        /// <summary>
        ///     上一次日志扫描的最大id
        /// </summary>
        static CommandQueueProcessor()
        {
            thread = new Thread(Running) {IsBackground = true};
            thread.Start();
        }

        /// <summary>
        ///     运行处理循环
        /// </summary>
        public static void Run()
        {
        }

        private static void Running()
        {
            //lastMaxID = 0;//仅测试
            RecoveryStartTasks();

            //todo 增加消息队列命令模式
            //RedisHelper.RedisListner((channel, msg) =>
            //{
            //    try
            //    {
            //        RedisCommondInfo redisCommondInfo = null;
            //        try
            //        {
            //            redisCommondInfo = new BSF.Serialization.JsonProvider().Deserialize<RedisCommondInfo>(msg);
            //        }
            //        catch
            //        {
            //        }
            //        if (redisCommondInfo != null)
            //        {
            //            if ((redisCommondInfo.CommondType == EnumCommondType.TaskCommand) &&
            //                (redisCommondInfo.NodeId == GlobalConfig.NodeID))
            //                RunCommond();
            //            if (redisCommondInfo.CommondType == EnumCommondType.ConfigUpdate)
            //                RedisHelper.RefreashRedisServerIP();
            //        }
            //        else
            //        {
            //            throw new Exception("redis命令无法识别");
            //        }
            //    }
            //    catch (Exception exp)
            //    {
            //        LogHelper.AddNodeError("Redis命令处理出错,msg:" + msg.NullToEmpty(), exp);
            //    }
            //}, info =>
            //{
            //    if (info != null)
            //        ZilLionLogManager.GetLogger().Error("Redis订阅出错," + info.Message.NullToEmpty(), info.Exception);
            //});

            RuningCommandLoop();
        }

        /// <summary>
        ///     恢复已开启的任务
        /// </summary>
        private static void RecoveryStartTasks()
        {
            try
            {
                ZilLionLogManager.GetLogger().Trace("当前节点启动成功,准备恢复已经开启的任务...");

                var response = TaskStateRespository.GetAllTaskState(ConfigurationManager.AppSettings["NodeId"]);
                var taskStates = new List<TaskStateEntity>();
                if ((response != null) && (response.TaskStates != null))
                    taskStates.AddRange(response.TaskStates.Where(x => x.Taskstatus == 0));


                foreach (var runlog in taskStates)
                    try
                    {
                        CommandFactory.Execute(new TaskConmmandEntity
                        {
                            CommandUpdateTime = DateTime.Now,
                            Commandname = EnumTaskCommandName.StartTask.ToString(),
                            Commandstate = (int) EnumTaskCommandState.None,
                            NodeId = ConfigurationManager.AppSettings["NodeId"],
                            Taskid = runlog.Taskid,
                            CommandId = string.Empty
                        });
                    }
                    catch (Exception ex)
                    {
                        ZilLionLogManager.GetLogger().Warn($"恢复已经开启的任务{JsonConvert.SerializeObject(runlog)}失败");
                    }
                ZilLionLogManager.GetLogger().Trace($"恢复已经开启的任务完毕，共{taskStates.Count}条任务重启");
            }
            catch (Exception exp)
            {
                ZilLionLogManager.GetLogger().Error(exp);
            }
        }

        /// <summary>
        ///     运行消息循环
        /// </summary>
        private static void RuningCommandLoop()
        {
            ZilLionLogManager.GetLogger().Trace("准备接受命令并运行消息循环...");
            while (true)
            {
                Thread.Sleep(1000);
                RunCommond();
                Thread.Sleep(1000);
            }
        }

        private static void RunCommond()
        {
            lock (_lockRunLoop)
            {
                try
                {
                    var unHandleCommands = new List<TaskConmmandEntity>();

                    var response =
                        TaskCommandRespository.GetUnHandleTaskConmmandEntities(
                            ConfigurationManager.AppSettings["NodeId"]);
                    if (response != null && response.TaskConmmands != null)
                    {
                        unHandleCommands.AddRange(response.TaskConmmands);
                    }

                    if (unHandleCommands.Any())
                        ZilLionLogManager.GetLogger().Trace("当前节点扫描到" + unHandleCommands.Count() + "条命令,并执行中....");

                    foreach (var command in unHandleCommands)
                        try
                        {
                            CommandFactory.Execute(command);
                            command.Commandstate = 1;
                            command.CommandUpdateTime = DateTime.Now;
                            TaskCommandRespository.SaveTaskConmmandEntity(command);
                            ZilLionLogManager.GetLogger().Trace(
                                $"当前节点执行命令成功! id:{command.CommandId},命令名:{command.Commandname},命令内容:{command.CommandContent}");
                        }
                        catch (Exception ex)
                        {
                            try
                            {
                                ZilLionLogManager.GetLogger().Error(ex);
                            }
                            catch
                            {
                            }
                        }
                }
                catch (Exception exp)
                {
                    ZilLionLogManager.GetLogger().Error(ex: exp, tags: "系统级不可恢复严重错误");
                }
            }
        }
    }
}